package com.jinly.ryder.account.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jinly.ryder.account.dao.UserInfoMapper;
import com.jinly.ryder.account.dao.entity.UserInfoDO;
import com.jinly.ryder.account.service.UserInfoService;
import com.jinly.ryder.account.service.mapping.UserInfoMapping;
import com.jinly.ryder.account.service.model.UserInfo;
import com.jinly.ryder.account.service.model.UserState;
import com.jinly.ryder.common.error.SystemErrorType;
import com.jinly.ryder.common.service.SystemSettingService;
import com.jinly.ryder.common.service.TemplateService;
import com.jinly.ryder.common.service.model.setting.BaseInfoSetting;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;

import javax.mail.internet.MimeMessage;
import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserInfoServiceImpl implements UserInfoService {

    public static final char[] CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
            , 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
            , 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

    private final UserInfoMapper userInfoMapper;
    private final UserInfoMapping userInfoMapping;
    private final JavaMailSenderImpl mailSender;
    private final TemplateService templateService;

    private final SystemSettingService systemSettingService;

    @Value("${spring.mail.username}")
    private String sendEmail;

    private static String randomPwd(int len) {
        Random r = new Random();
        char[] chars = new char[len];
        for (int i = 0; i < chars.length; i++) {
            chars[i] = CHARS[r.nextInt(CHARS.length)];
        }
        return new String(chars);
    }

    @Override
    public Page<UserInfo> queryUserPage(Page page, UserInfo userInfo) {
        Wrapper<UserInfoDO> queryWrapper = new QueryWrapper<UserInfoDO>().lambda()
                .like(userInfo.getUsername() != null, UserInfoDO::getUsername, userInfo.getUsername())
                .like(userInfo.getNickname() != null, UserInfoDO::getNickname, userInfo.getNickname())
                .like(userInfo.getMobile() != null, UserInfoDO::getMobile, userInfo.getMobile())
                .like(userInfo.getEmail() != null, UserInfoDO::getEmail, userInfo.getEmail())
                .eq(userInfo.getState() != null, UserInfoDO::getState, userInfo.getState());
        return userInfoMapping.toModelPage(userInfoMapper.selectPage(page, queryWrapper));
    }

    @Override
    public UserInfo getUserInfo(Long userId) {
        return userInfoMapping.toModel(userInfoMapper.selectById(userId));
    }

    @Override
    public void addUserInfo(UserInfo userInfo) {
        String password = randomPwd(12);
        userInfo.setPassword(password);
        userInfo.setPassword(DigestUtils.md5DigestAsHex(userInfo.getPassword().getBytes()));
        userInfo.setState(UserState.NORMAL);
        userInfoMapper.insert(userInfoMapping.toEntity(userInfo));
        sendRegisterMail(userInfo, password);
    }

    /**
     * 发送注册邮件
     *
     * @param userInfo
     * @param password
     */
    private void sendRegisterMail(UserInfo userInfo, String password) {
        if (ObjectUtils.isEmpty(userInfo.getEmail())) return;
        try {
            BaseInfoSetting baseInfoSetting = systemSettingService.getSettingItem(BaseInfoSetting.class);
            Map<String, String> paramMap = new HashMap<>();
            paramMap.put("username", userInfo.getUsername());
            paramMap.put("nickname", userInfo.getNickname());
            paramMap.put("password", password);
            paramMap.put("url", baseInfoSetting != null ? baseInfoSetting.getUrl() : "");
            String html = templateService.getLocalResult("mail/registerTemplate.html", paramMap);
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
            helper.setFrom(sendEmail);
            helper.setTo(userInfo.getEmail());
            helper.setSubject("Deploy注册成功");
            helper.setText(html, true);
            this.mailSender.send(mimeMessage);
        } catch (Exception ex) {
            log.error("发送邮件失败", ex);
            SystemErrorType.INTERNAL_SERVER_ERROR.throwError("发送邮件失败");
        }
    }

    @Override
    public void updateUserInfo(UserInfo userInfo) {
        if (!ObjectUtils.isEmpty(userInfo.getPassword())) {
            userInfo.setPassword(DigestUtils.md5DigestAsHex(userInfo.getPassword().getBytes()));
        }
        userInfoMapper.updateById(userInfoMapping.toEntity(userInfo));
    }

    @Override
    public UserInfo checkUserInfo(String username, String password) {
        Wrapper<UserInfoDO> queryWrapper = new QueryWrapper<UserInfoDO>().lambda()
                .eq(UserInfoDO::getUsername, username)
                .eq(UserInfoDO::getPassword, DigestUtils.md5DigestAsHex(password.getBytes()));
        return userInfoMapping.toModel(userInfoMapper.selectOne(queryWrapper));
    }

    @Override
    public List<UserInfo> batchQueryUsers(Set<Long> userIds) {
        return userInfoMapping.toModelList(userInfoMapper.selectBatchIds(userIds));
    }

    @Override
    public List<UserInfo> batchQueryUsersByUserName(Set<String> collect) {
        if (collect.size() == 0) return Collections.emptyList();
        Wrapper<UserInfoDO> queryWrapper = new QueryWrapper<UserInfoDO>().lambda()
                .in(UserInfoDO::getUsername, collect);
        return userInfoMapping.toModelList(userInfoMapper.selectList(queryWrapper));
    }
}
